package org.yzh.scheduler.schedule;

import jakarta.annotation.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledFuture;

@Component
public class SchedulerManager {

    private final Logger log = LoggerFactory.getLogger(SchedulerManager.class);

    private final ConcurrentHashMap<String, ScheduledFuture<?>> jobMap = new ConcurrentHashMap<>();

    @Resource
    private RemoteHttpTrigger remoteHttpTrigger;

    @Resource
    private TaskScheduler scheduler;

    public void createJob(String name, String group, String cronExpression) {
        String jobKey = jobKey(name, group);
        if (jobMap.containsKey(jobKey))
            return;

        CronTrigger trigger = new CronTrigger(cronExpression);
        ScheduledFuture<?> schedule = scheduler.schedule(() -> {
            try {
                if (!remoteHttpTrigger.trigger(name, group)) {
                    delete(name, group);
                }
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            }
        }, trigger);
        jobMap.put(jobKey, schedule);
    }

    public void updateCron(String name, String group, String cronExpression) {
        if (delete(name, group)) {
            createJob(name, group, cronExpression);
        }
    }

    public boolean delete(String name, String group) {
        ScheduledFuture<?> future = jobMap.remove(jobKey(name, group));
        if (future != null)
            return future.cancel(true);
        return false;
    }

    public void runOnce(String name, String group) {
        ScheduledFuture<?> future = jobMap.get(jobKey(name, group));
        if (future != null)
            remoteHttpTrigger.trigger(name, group);
    }

    public Future.State getTriggerState(String name, String group) {
        ScheduledFuture<?> future = jobMap.get(jobKey(name, group));
        if (future != null) {
            return future.state();
        }
        return Future.State.CANCELLED;
    }

    public boolean checkExists(String name, String group) {
        return jobMap.containsKey(jobKey(name, group));
    }

    public String jobKey(String name, String group) {
        return group + ":" + name;
    }
}